home *** CD-ROM | disk | FTP | other *** search
/ ADA Programming Guide / ADA Programming Guide.iso / ada_gnu / adainc / a-stwibo.adb < prev    next >
Text File  |  1996-01-30  |  41KB  |  1,285 lines

  1. ------------------------------------------------------------------------------
  2. --                                                                          --
  3. --                         GNAT RUNTIME COMPONENTS                          --
  4. --                                                                          --
  5. --             A D A . S T R I N G S . W I D E _ B O U N D E D              --
  6. --                                                                          --
  7. --                                 S p e c                                  --
  8. --                                                                          --
  9. --                            $Revision: 1.8 $                              --
  10. --                                                                          --
  11. --           Copyright (c) 1992,1993,1994 NYU, All Rights Reserved          --
  12. --                                                                          --
  13. -- The GNAT library is free software; you can redistribute it and/or modify --
  14. -- it under terms of the GNU Library General Public License as published by --
  15. -- the Free Software  Foundation; either version 2, or (at your option) any --
  16. -- later version.  The GNAT library is distributed in the hope that it will --
  17. -- be useful, but WITHOUT ANY WARRANTY;  without even  the implied warranty --
  18. -- of MERCHANTABILITY  or  FITNESS FOR  A PARTICULAR PURPOSE.  See the  GNU --
  19. -- Library  General  Public  License for  more  details.  You  should  have --
  20. -- received  a copy of the GNU  Library  General Public License  along with --
  21. -- the GNAT library;  see the file  COPYING.LIB.  If not, write to the Free --
  22. -- Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.        --
  23. --                                                                          --
  24. ------------------------------------------------------------------------------
  25.  
  26.  
  27. with Ada.Strings.Wide_Search;
  28. with Ada.Strings.Wide_Maps;   use Ada.Strings.Wide_Maps;
  29.  
  30. package body Ada.Strings.Wide_Bounded is
  31.  
  32.    package body Generic_Bounded_Length is
  33.  
  34.       ---------
  35.       -- "=" --
  36.       ---------
  37.  
  38.       function "=" (Left, Right : in Bounded_Wide_String) return Boolean is
  39.       begin
  40.          return Left.Length = Right.Length
  41.            and then Left.Data (1 .. Left.Length) =
  42.                     Right.Data (1 .. Right.Length);
  43.       end "=";
  44.  
  45.       ---------
  46.       -- "<" --
  47.       ---------
  48.  
  49.       function "<"  (Left, Right : in Bounded_Wide_String) return Boolean is
  50.       begin
  51.          return Left.Data (1 .. Left.Length) < Right.Data (1 .. Right.Length);
  52.       end "<";
  53.  
  54.       ----------
  55.       -- "<=" --
  56.       ----------
  57.  
  58.       function "<=" (Left, Right : in Bounded_Wide_String) return Boolean is
  59.       begin
  60.          return Left.Data (1 .. Left.Length) <= Right.Data (1 .. Right.Length);
  61.       end "<=";
  62.  
  63.       ---------
  64.       -- ">" --
  65.       ---------
  66.  
  67.       function ">"  (Left, Right : in Bounded_Wide_String) return Boolean is
  68.       begin
  69.          return Left.Data (1 .. Left.Length) > Right.Data (1 .. Right.Length);
  70.       end ">";
  71.  
  72.       ----------
  73.       -- ">=" --
  74.       ----------
  75.  
  76.       function ">=" (Left, Right : in Bounded_Wide_String) return Boolean is
  77.       begin
  78.          return Left.Data (1 .. Left.Length) >= Right.Data (1 .. Right.Length);
  79.       end ">=";
  80.  
  81.       ---------
  82.       -- "*" --
  83.       ---------
  84.  
  85.       function "*" (Left : in Natural; Right : in Wide_Character)
  86.          return Bounded_Wide_String is
  87.       begin
  88.          return Replicate (Left, Right, Strings.Error);
  89.       end "*";
  90.  
  91.       function "*" (Left  : in Natural; Right : in Wide_String)
  92.          return Bounded_Wide_String is
  93.       begin
  94.          return Replicate (Left, Right, Strings.Error);
  95.       end "*";
  96.  
  97.       function "*" (Left : in Natural; Right : in Bounded_Wide_String)
  98.          return Bounded_Wide_String is
  99.       begin
  100.          return Replicate (Left, Right, Strings.Error);
  101.       end "*";
  102.  
  103.       ---------
  104.       -- "&" --
  105.       ---------
  106.  
  107.       function "&" (Left, Right : in Bounded_Wide_String)
  108.          return Bounded_Wide_String is
  109.       begin
  110.          return Append (Left, Right, Drop => Strings.Error);
  111.       end "&";
  112.  
  113.       function "&" (Left : in Bounded_Wide_String; Right : in Wide_String)
  114.          return Bounded_Wide_String is
  115.       begin
  116.          return Append (Left, Right, Drop => Strings.Error);
  117.       end "&";
  118.  
  119.       function "&" (Left : in Wide_String; Right : in Bounded_Wide_String)
  120.          return Bounded_Wide_String is
  121.       begin
  122.          return Append (Left, Right, Drop => Strings.Error);
  123.       end "&";
  124.  
  125.       function "&" (Left : in Bounded_Wide_String; Right : in Wide_Character)
  126.          return Bounded_Wide_String is
  127.       begin
  128.          return Append (Left, Right, Drop => Strings.Error);
  129.       end "&";
  130.  
  131.       function "&" (Left : in Wide_Character; Right : in Bounded_Wide_String)
  132.          return Bounded_Wide_String is
  133.       begin
  134.          return Append (Left, Right, Drop => Strings.Error);
  135.       end "&";
  136.  
  137.       ------------
  138.       -- Append --
  139.       ------------
  140.  
  141.       --  Case of Bounded_Wide_String and Bounded_Wide_String
  142.  
  143.       function Append
  144.         (Left, Right : in Bounded_Wide_String;
  145.          Drop        : in Strings.Truncation := Strings.Error)
  146.          return        Bounded_Wide_String
  147.       is
  148.          Result : Bounded_Wide_String;
  149.          Llen   : constant Positive := Left.Length;
  150.          Rlen   : constant Positive := Right.Length;
  151.  
  152.       begin
  153.          if Llen + Rlen <= Max_Length then
  154.             Result.Length := Llen + Rlen;
  155.             Result.Data (1 .. Llen) := Left.Data;
  156.             Result.Data (Llen + 1 .. Llen + Rlen) := Right.Data;
  157.  
  158.          else
  159.             Result.Length := Max_Length;
  160.  
  161.             case Drop is
  162.                when Strings.Right =>
  163.                   if Llen >= Max_Length then
  164.                      Result.Data (1 .. Max_Length) :=
  165.                        Left.Data (1 .. Max_Length);
  166.  
  167.                   else
  168.                      Result.Data (1 .. Llen) := Left.Data;
  169.                      Result.Data (Llen + 1 .. Max_Length) :=
  170.                        Right.Data (1 .. Max_Length - Llen);
  171.                   end if;
  172.  
  173.                when Strings.Left =>
  174.                   if Rlen >= Max_Length then
  175.                      Result.Data (1 .. Max_Length) :=
  176.                        Right.Data (Rlen - (Max_Length - 1) .. Rlen);
  177.  
  178.                   else
  179.                      Result.Data (1 .. Max_Length - Rlen) :=
  180.                        Left.Data (Llen - (Max_Length - Rlen + 1) .. Llen);
  181.                      Result.Data (Max_Length - Rlen + 1 .. Max_Length) :=
  182.                        Right.Data;
  183.                   end if;
  184.  
  185.                when Strings.Error =>
  186.                   raise Strings.Length_Error;
  187.             end case;
  188.          end if;
  189.  
  190.          return Result;
  191.       end Append;
  192.  
  193.       --  Case of Bounded_Wide_String and Wide_String
  194.  
  195.       function Append
  196.         (Left  : in Bounded_Wide_String;
  197.          Right : in Wide_String;
  198.          Drop  : in Strings.Truncation := Strings.Error)
  199.          return  Bounded_Wide_String
  200.       is
  201.          Result : Bounded_Wide_String;
  202.          Llen   : constant Positive := Left.Length;
  203.          Rlen   : constant Positive := Right'Length;
  204.  
  205.       begin
  206.          if Llen + Rlen <= Max_Length then
  207.             Result.Length := Llen + Rlen;
  208.             Result.Data (1 .. Llen) := Left.Data;
  209.             Result.Data (Llen + 1 .. Llen + Rlen) := Right;
  210.  
  211.          else
  212.             Result.Length := Max_Length;
  213.  
  214.             case Drop is
  215.                when Strings.Right =>
  216.                   if Llen >= Max_Length then
  217.                      Result.Data (1 .. Max_Length) :=
  218.                        Left.Data (1 .. Max_Length);
  219.  
  220.                   else
  221.                      Result.Data (1 .. Llen) := Left.Data;
  222.                      Result.Data (Llen + 1 .. Max_Length) :=
  223.                        Right (1 .. Max_Length - Llen);
  224.                   end if;
  225.  
  226.                when Strings.Left =>
  227.                   if Rlen >= Max_Length then
  228.                      Result.Data (1 .. Max_Length) :=
  229.                        Right (Rlen - (Max_Length - 1) .. Rlen);
  230.  
  231.                   else
  232.                      Result.Data (1 .. Max_Length - Rlen) :=
  233.                        Left.Data (Llen - (Max_Length - Rlen + 1) .. Llen);
  234.                      Result.Data (Max_Length - Rlen + 1 .. Max_Length) :=
  235.                        Right;
  236.                   end if;
  237.  
  238.                when Strings.Error =>
  239.                   raise Strings.Length_Error;
  240.             end case;
  241.          end if;
  242.  
  243.          return Result;
  244.       end Append;
  245.  
  246.       --  Case of Wide_String and Bounded_Wide_String
  247.  
  248.       function Append
  249.         (Left  : in Wide_String;
  250.          Right : in Bounded_Wide_String;
  251.          Drop  : in Strings.Truncation := Strings.Error)
  252.          return  Bounded_Wide_String
  253.       is
  254.          Result : Bounded_Wide_String;
  255.          Llen   : constant Positive := Left'Length;
  256.          Rlen   : constant Positive := Right.Length;
  257.  
  258.       begin
  259.          if Llen + Rlen <= Max_Length then
  260.             Result.Length := Llen + Rlen;
  261.             Result.Data (1 .. Llen) := Left;
  262.             Result.Data (Llen + 1 .. Llen + Rlen) := Right.Data;
  263.  
  264.          else
  265.             Result.Length := Max_Length;
  266.  
  267.             case Drop is
  268.                when Strings.Right =>
  269.                   if Llen >= Max_Length then
  270.                      Result.Data (1 .. Max_Length) := Left (1 .. Max_Length);
  271.  
  272.                   else
  273.                      Result.Data (1 .. Llen) := Left;
  274.                      Result.Data (Llen + 1 .. Max_Length) :=
  275.                        Right.Data (1 .. Max_Length - Llen);
  276.                   end if;
  277.  
  278.                when Strings.Left =>
  279.                   if Rlen >= Max_Length then
  280.                      Result.Data (1 .. Max_Length) :=
  281.                        Right.Data (Rlen - (Max_Length - 1) .. Rlen);
  282.  
  283.                   else
  284.                      Result.Data (1 .. Max_Length - Rlen) :=
  285.                        Left (Llen - (Max_Length - Rlen + 1) .. Llen);
  286.                      Result.Data (Max_Length - Rlen + 1 .. Max_Length) :=
  287.                        Right.Data;
  288.                   end if;
  289.  
  290.                when Strings.Error =>
  291.                   raise Strings.Length_Error;
  292.             end case;
  293.          end if;
  294.  
  295.          return Result;
  296.       end Append;
  297.  
  298.       --  Case of Bounded_Wide_String and Wide_Character
  299.  
  300.       function Append
  301.         (Left  : in Bounded_Wide_String;
  302.          Right : in Wide_Character;
  303.          Drop  : in Strings.Truncation := Strings.Error)
  304.          return  Bounded_Wide_String
  305.       is
  306.          Result : Bounded_Wide_String;
  307.          Llen   : constant Positive := Left.Length;
  308.  
  309.       begin
  310.          if Llen  < Max_Length then
  311.             Result.Length := Llen + 1;
  312.             Result.Data (1 .. Llen) := Left.Data (1 .. Llen);
  313.             Result.Data (Llen + 1) := Right;
  314.  
  315.          else
  316.             Result.Length := Max_Length;
  317.  
  318.             case Drop is
  319.                when Strings.Right =>
  320.                   Result.Data := Left.Data;
  321.  
  322.                when Strings.Left =>
  323.                   Result.Data (1 .. Max_Length - 1) :=
  324.                     Left.Data (2 .. Max_Length);
  325.                   Result.Data (Max_Length) := Right;
  326.  
  327.                when Strings.Error =>
  328.                   raise Strings.Length_Error;
  329.             end case;
  330.          end if;
  331.  
  332.          return Result;
  333.       end Append;
  334.  
  335.       --  Case of Wide_Character and Bounded_Wide_String
  336.  
  337.       function Append
  338.         (Left  : in Wide_Character;
  339.          Right : in Bounded_Wide_String;
  340.          Drop  : in Strings.Truncation := Strings.Error)
  341.          return  Bounded_Wide_String
  342.       is
  343.          Result : Bounded_Wide_String;
  344.          Rlen   : constant Positive := Right.Length;
  345.  
  346.       begin
  347.          if Rlen < Max_Length then
  348.             Result.Length := Rlen + 1;
  349.             Result.Data (1) := Left;
  350.             Result.Data (2 .. Rlen + 1) := Right.Data (1 .. Rlen);
  351.  
  352.          else
  353.             Result.Length := Max_Length;
  354.  
  355.             case Drop is
  356.                when Strings.Right =>
  357.                   Result.Data (1) := Left;
  358.                   Result.Data (2 .. Max_Length) :=
  359.                     Right.Data (1 .. Max_Length - 1);
  360.  
  361.                when Strings.Left =>
  362.                   Result.Data (1 .. Max_Length) :=
  363.                     Right.Data (Rlen - (Max_Length - 1) .. Rlen);
  364.  
  365.                when Strings.Error =>
  366.                   raise Strings.Length_Error;
  367.             end case;
  368.          end if;
  369.  
  370.          return Result;
  371.       end Append;
  372.  
  373.       -----------
  374.       -- Count --
  375.       -----------
  376.  
  377.       function Count
  378.         (Source   : in Bounded_Wide_String;
  379.          Pattern  : in Wide_String;
  380.          Mapping  : in Wide_Maps.Wide_Character_Mapping := Wide_Maps.Identity)
  381.          return     Natural is
  382.  
  383.       begin
  384.          return
  385.            Wide_Search.Count
  386.              (Source.Data (1 .. Source.Length), Pattern, Mapping);
  387.       end Count;
  388.  
  389.       function Count
  390.         (Source   : in Bounded_Wide_String;
  391.          Pattern  : in Wide_String;
  392.          Mapping  : in Wide_Maps.Wide_Character_Mapping_Function)
  393.          return     Natural
  394.       is
  395.       begin
  396.          return
  397.            Wide_Search.Count
  398.              (Source.Data (1 .. Source.Length), Pattern, Mapping);
  399.       end Count;
  400.  
  401.       function Count (Source : in Bounded_Wide_String;
  402.                       Set    : in Wide_Maps.Wide_Character_Set)
  403.         return Natural is
  404.  
  405.       begin
  406.          return Wide_Search.Count (Source.Data, Set);
  407.       end Count;
  408.  
  409.       ------------
  410.       -- Delete --
  411.       ------------
  412.  
  413.       function Delete
  414.         (Source  : in Bounded_Wide_String;
  415.          From    : in Positive;
  416.          Through : in Natural)
  417.          return    Bounded_Wide_String
  418.       is
  419.          Slen       : constant Natural := Source.Length;
  420.          Num_Delete : constant Integer := Through - From + 1;
  421.          Result     : Bounded_Wide_String;
  422.  
  423.       begin
  424.          if Num_Delete < 0 then
  425.             Result.Length := Slen;
  426.             Result.Data (1 .. Slen) := Source.Data (1 .. Slen);
  427.  
  428.          elsif From > Slen then
  429.             raise Strings.Index_Error;
  430.  
  431.          elsif Through >= Slen then
  432.             Result.Data (1 .. From - 1) := Source.Data (1 .. From - 1);
  433.             Result.Length := From - 1;
  434.  
  435.          else
  436.             Result.Data (1 .. From - 1) := Source.Data (1 .. From - 1);
  437.             Result.Length := Slen - Num_Delete;
  438.             Result.Data (From .. Result.Length) :=
  439.               Source.Data (Through + 1 .. Slen);
  440.          end if;
  441.  
  442.          return Result;
  443.       end Delete;
  444.  
  445.       procedure Delete
  446.         (Source  : in out Bounded_Wide_String;
  447.          From    : in Positive;
  448.          Through : in Natural)
  449.       is
  450.          Slen       : constant Natural := Source.Length;
  451.          Num_Delete : constant Integer := Through - From + 1;
  452.  
  453.       begin
  454.          if Num_Delete < 0 then
  455.             return;
  456.  
  457.          elsif From > Slen then
  458.             raise Strings.Index_Error;
  459.  
  460.          elsif Through >= Slen then
  461.             Source.Length := From - 1;
  462.  
  463.          else
  464.             Source.Length := Slen - Num_Delete;
  465.             Source.Data (From .. Source.Length) :=
  466.               Source.Data (Through + 1 .. Slen);
  467.          end if;
  468.       end Delete;
  469.  
  470.       -------------
  471.       -- Element --
  472.       -------------
  473.  
  474.       function Element
  475.         (Source : in Bounded_Wide_String;
  476.          Index  : in Positive)
  477.          return   Wide_Character
  478.       is
  479.       begin
  480.          if Index in 1 .. Source.Length then
  481.             return Source.Data (Index);
  482.          else
  483.             raise Strings.Index_Error;
  484.          end if;
  485.       end Element;
  486.  
  487.       ----------------
  488.       -- Find_Token --
  489.       ----------------
  490.  
  491.       procedure Find_Token
  492.         (Source : in Bounded_Wide_String;
  493.          Set    : in Wide_Maps.Wide_Character_Set;
  494.          Test   : in Strings.Membership;
  495.          First  : out Positive;
  496.          Last   : out Natural)
  497.       is
  498.       begin
  499.          Wide_Search.Find_Token
  500.            (Source.Data (1 .. Source.Length), Set, Test, First, Last);
  501.       end Find_Token;
  502.  
  503.       ----------
  504.       -- Head --
  505.       ----------
  506.  
  507.       function Head
  508.         (Source : in Bounded_Wide_String;
  509.          Count  : in Natural;
  510.          Pad    : in Wide_Character := Blank;
  511.          Drop   : in Strings.Truncation := Strings.Error)
  512.          return   Bounded_Wide_String
  513.       is
  514.          Result : Bounded_Wide_String;
  515.          Slen   : constant Natural := Source.Length;
  516.          Npad   : constant Integer := Count - Slen;
  517.  
  518.       begin
  519.          if Npad <= 0 then
  520.             Result.Length := Count;
  521.             Result.Data (1 .. Count) := Source.Data (1 .. Count);
  522.  
  523.          elsif Count <= Max_Length then
  524.             Result.Length := Count;
  525.             Result.Data (1 .. Slen) := Source.Data (1 .. Slen);
  526.             Result.Data (Slen + 1 .. Count) := (others => Pad);
  527.  
  528.          else
  529.             Result.Length := Max_Length;
  530.  
  531.             case Drop is
  532.                when Strings.Right =>
  533.                   Result.Data (1 .. Slen) := Source.Data (1 .. Slen);
  534.                   Result.Data (Slen + 1 .. Max_Length) := (others => Pad);
  535.  
  536.                when Strings.Left =>
  537.                   if Npad > Max_Length then
  538.                      Result.Data := (others => Pad);
  539.  
  540.                   else
  541.                      Result.Data (1 .. Max_Length - Npad) :=
  542.                        Source.Data (Count - Max_Length + 1 .. Slen);
  543.                      Result.Data (Max_Length - Npad + 1 .. Max_Length) :=
  544.                        (others => Pad);
  545.                   end if;
  546.  
  547.                when Strings.Error =>
  548.                   raise Strings.Length_Error;
  549.             end case;
  550.          end if;
  551.  
  552.          return Result;
  553.       end Head;
  554.  
  555.       -----------
  556.       -- Index --
  557.       -----------
  558.  
  559.       function Index
  560.         (Source   : in Bounded_Wide_String;
  561.          Pattern  : in Wide_String;
  562.          Going    : in Strings.Direction := Strings.Forward;
  563.          Mapping  : in Wide_Maps.Wide_Character_Mapping := Wide_Maps.Identity)
  564.          return     Natural is
  565.  
  566.       begin
  567.          return Wide_Search.Index
  568.            (Source.Data (1 .. Source.Length), Pattern, Going, Mapping);
  569.       end Index;
  570.  
  571.       function Index
  572.         (Source   : in Bounded_Wide_String;
  573.          Pattern  : in Wide_String;
  574.          Going    : in Strings.Direction := Strings.Forward;
  575.          Mapping  : in Wide_Maps.Wide_Character_Mapping_Function)
  576.          return     Natural
  577.       is
  578.       begin
  579.          return Wide_Search.Index
  580.            (Source.Data (1 .. Source.Length), Pattern, Going, Mapping);
  581.       end Index;
  582.  
  583.       function Index
  584.         (Source : in Bounded_Wide_String;
  585.          Set    : in Wide_Maps.Wide_Character_Set;
  586.          Test   : in Strings.Membership := Strings.Inside;
  587.          Going  : in Strings.Direction  := Strings.Forward)
  588.          return   Natural
  589.       is
  590.       begin
  591.          return Wide_Search.Index
  592.            (Source.Data (1 .. Source.Length), Set, Test, Going);
  593.       end Index;
  594.  
  595.       ---------------------
  596.       -- Index_Non_Blank --
  597.       ---------------------
  598.  
  599.       function Index_Non_Blank
  600.         (Source : in Bounded_Wide_String;
  601.          Going  : in Strings.Direction := Strings.Forward)
  602.          return   Natural
  603.       is
  604.       begin
  605.          return
  606.            Wide_Search.Index_Non_Blank
  607.              (Source.Data (1 .. Source.Length), Going);
  608.       end Index_Non_Blank;
  609.  
  610.       ------------
  611.       -- Insert --
  612.       ------------
  613.  
  614.       function Insert
  615.         (Source   : in Bounded_Wide_String;
  616.          Before   : in Positive;
  617.          New_Item : in Wide_String;
  618.          Drop     : in Strings.Truncation := Strings.Error)
  619.          return     Bounded_Wide_String
  620.       is
  621.          Slen    : constant Natural := Source.Length;
  622.          Nlen    : constant Natural := New_Item'Length;
  623.          Tlen    : constant Natural := Slen + Nlen;
  624.          Blen    : constant Natural := Before - 1;
  625.          Alen    : constant Integer := Slen - Blen;
  626.          Droplen : constant Integer := Tlen - Max_Length;
  627.          Result  : Bounded_Wide_String;
  628.  
  629.          --  Tlen is the length of the total string before possible truncation.
  630.          --  Blen, Alen are the lengths of the before and after pieces of the
  631.          --  source string.
  632.  
  633.       begin
  634.          if Alen < 0 then
  635.             raise Index_Error;
  636.  
  637.          elsif Droplen <= 0 then
  638.             Result.Length := Tlen;
  639.             Result.Data (1 .. Blen) := Source.Data (1 .. Blen);
  640.             Result.Data (Before .. Before + Nlen - 1) := New_Item;
  641.             Result.Data (Before + Nlen .. Tlen) :=
  642.               Source.Data (Before .. Slen);
  643.  
  644.          else
  645.             Result.Length := Max_Length;
  646.  
  647.             case Drop is
  648.                when Strings.Right =>
  649.                   Result.Data (1 .. Blen) := Source.Data (1 .. Blen);
  650.  
  651.                   if Droplen > Alen then
  652.                      Result.Data (Before .. Max_Length) :=
  653.                        New_Item (New_Item'First
  654.                                    .. New_Item'First + Max_Length - Before);
  655.                   else
  656.                      Result.Data (Before .. Before + Nlen - 1) := New_Item;
  657.                      Result.Data (Before + Nlen .. Max_Length) :=
  658.                        Source.Data (Before .. Slen - Droplen);
  659.                   end if;
  660.  
  661.                when Strings.Left =>
  662.                   Result.Data (Max_Length - (Alen - 1) .. Max_Length) :=
  663.                     Source.Data (Before .. Slen);
  664.  
  665.                   if Droplen >= Blen then
  666.                      Result.Data (1 .. Max_Length - Alen) :=
  667.                        New_Item (New_Item'Last - (Max_Length - Alen) + 1
  668.                                    .. New_Item'Last);
  669.                   else
  670.                      Result.Data
  671.                        (Blen - Droplen + 1 .. Max_Length - Alen) :=
  672.                          New_Item;
  673.                      Result.Data (1 .. Blen - Droplen) :=
  674.                        Source.Data (Droplen + 1 .. Blen);
  675.                   end if;
  676.  
  677.                when Strings.Error =>
  678.                   raise Strings.Length_Error;
  679.             end case;
  680.          end if;
  681.  
  682.          return Result;
  683.       end Insert;
  684.  
  685.       procedure Insert
  686.         (Source   : in out Bounded_Wide_String;
  687.          Before   : in Positive;
  688.          New_Item : in Wide_String;
  689.          Drop     : in Strings.Truncation := Strings.Error)
  690.       is
  691.       begin
  692.          --  We do a double copy here because this is one of the situations
  693.          --  in which we move data to the right, and at least at the moment,
  694.          --  GNAT is not handling such cases correctly ???
  695.  
  696.          Source := Insert (Source, Before, New_Item, Drop);
  697.       end Insert;
  698.  
  699.       ------------
  700.       -- Length --
  701.       ------------
  702.  
  703.       function Length (Source : in Bounded_Wide_String) return Length_Range is
  704.       begin
  705.          return Source.Length;
  706.       end Length;
  707.  
  708.       ---------------
  709.       -- Overwrite --
  710.       ---------------
  711.  
  712.       function Overwrite
  713.         (Source    : in Bounded_Wide_String;
  714.          Position  : in Positive;
  715.          New_Item  : in Wide_String;
  716.          Drop      : in Strings.Truncation := Strings.Error)
  717.          return      Bounded_Wide_String
  718.       is
  719.          Result  : Bounded_Wide_String;
  720.          Endpos  : constant Positive := Position + New_Item'Length - 1;
  721.          Slen    : constant Natural  := Source.Length;
  722.          Droplen : Natural;
  723.  
  724.       begin
  725.          if Endpos <= Slen then
  726.             Result.Data (1 .. Position - 1) := Source.Data (1 .. Position - 1);
  727.             Result.Data (Position .. Endpos) := New_Item;
  728.             Result.Length := Source.Length;
  729.  
  730.          elsif Endpos <= Max_Length then
  731.             Result.Data (1 .. Position - 1) := Source.Data (1 .. Position - 1);
  732.             Result.Data (Position .. Endpos) := New_Item;
  733.             Result.Length := Endpos;
  734.  
  735.          else
  736.             Result.Length := Max_Length;
  737.             Droplen := Endpos - Max_Length;
  738.  
  739.             case Drop is
  740.                when Strings.Right =>
  741.                   Result.Data (1 .. Position - 1) :=
  742.                     Source.Data (1 .. Position - 1);
  743.                   Result.Data (Position .. Max_Length) :=
  744.                     New_Item (New_Item'First .. New_Item'Last - Droplen);
  745.  
  746.                when Strings.Left =>
  747.                   if New_Item'Length > Max_Length then
  748.                      Result.Data (1 .. Max_Length) :=
  749.                         New_Item (New_Item'Last - Max_Length + 1 ..
  750.                                   New_Item'Last);
  751.  
  752.                   else
  753.                      Result.Data (1 .. Max_Length - New_Item'Length) :=
  754.                        Source.Data (Droplen + 1 .. Position - 1);
  755.                      Result.Data
  756.                        (Max_Length - New_Item'Length + 1 .. Max_Length) :=
  757.                          New_Item;
  758.                   end if;
  759.  
  760.                when Strings.Error =>
  761.                   raise Strings.Length_Error;
  762.             end case;
  763.          end if;
  764.  
  765.          return Result;
  766.       end Overwrite;
  767.  
  768.       procedure Overwrite
  769.         (Source    : in out Bounded_Wide_String;
  770.          Position  : in Positive;
  771.          New_Item  : in Wide_String;
  772.          Drop      : in Strings.Truncation := Strings.Error)
  773.       is
  774.          Endpos  : constant Positive := Position + New_Item'Length - 1;
  775.          Slen    : constant Natural  := Source.Length;
  776.          Droplen : Natural;
  777.  
  778.       begin
  779.          if Endpos <= Slen then
  780.             Source.Data (Position .. Endpos) := New_Item;
  781.  
  782.          elsif Endpos <= Max_Length then
  783.             Source.Data (Position .. Endpos) := New_Item;
  784.             Source.Length := Endpos;
  785.  
  786.          else
  787.             Source.Length := Max_Length;
  788.             Droplen := Endpos - Max_Length;
  789.  
  790.             case Drop is
  791.                when Strings.Right =>
  792.                   Source.Data (Position .. Max_Length) :=
  793.                     New_Item (New_Item'First .. New_Item'Last - Droplen);
  794.  
  795.                when Strings.Left =>
  796.                   if New_Item'Length > Max_Length then
  797.                      Source.Data (1 .. Max_Length) :=
  798.                         New_Item (New_Item'Last - Max_Length + 1 ..
  799.                                   New_Item'Last);
  800.  
  801.                   else
  802.                      Source.Data (1 .. Max_Length - New_Item'Length) :=
  803.                        Source.Data (Droplen + 1 .. Position - 1);
  804.                      Source.Data
  805.                        (Max_Length - New_Item'Length + 1 .. Max_Length) :=
  806.                          New_Item;
  807.                   end if;
  808.  
  809.                when Strings.Error =>
  810.                   raise Strings.Length_Error;
  811.             end case;
  812.          end if;
  813.       end Overwrite;
  814.  
  815.       ---------------------
  816.       -- Replace_Element --
  817.       ---------------------
  818.  
  819.       procedure Replace_Element
  820.         (Source : in out Bounded_Wide_String;
  821.          Index  : in Positive;
  822.          By     : in Wide_Character)
  823.       is
  824.       begin
  825.          if Index <= Source.Length then
  826.             Source.Data (Index) := By;
  827.          else
  828.             raise Strings.Index_Error;
  829.          end if;
  830.       end Replace_Element;
  831.  
  832.       -------------------
  833.       -- Replace_Slice --
  834.       -------------------
  835.  
  836.       function Replace_Slice
  837.         (Source   : in Bounded_Wide_String;
  838.          Low      : in Positive;
  839.          High     : in Natural;
  840.          By       : in Wide_String;
  841.          Drop     : in Strings.Truncation := Strings.Error)
  842.          return     Bounded_Wide_String
  843.       is
  844.          Slen : constant Natural := Source.Length;
  845.  
  846.       begin
  847.          if Low > Slen + 1 then
  848.             raise Strings.Index_Error;
  849.  
  850.          elsif High < Low then
  851.             return Insert (Source, Low, By, Drop);
  852.  
  853.          else
  854.             declare
  855.                Blen    : constant Natural := Low - 1;
  856.                Alen    : constant Natural := Slen - High;
  857.                Tlen    : constant Natural := Blen + By'Length + Alen;
  858.                Droplen : constant Integer := Tlen - Max_Length;
  859.                Result  : Bounded_Wide_String;
  860.  
  861.                --  Tlen is the total length of the result string before any
  862.                --  truncation. Blen and Alen are the lengths of the pieces
  863.                --  of the original string that end up in the result string
  864.                --  before and after the replaced slice.
  865.  
  866.             begin
  867.                if Droplen <= 0 then
  868.                   Result.Length := Tlen;
  869.                   Result.Data (1 .. Blen) := Source.Data (1 .. Blen);
  870.                   Result.Data (Low .. Low + By'Length - 1) := By;
  871.                   Result.Data (Low + By'Length .. Tlen) :=
  872.                     Source.Data (High + 1 .. Slen);
  873.  
  874.                else
  875.                   Result.Length := Max_Length;
  876.  
  877.                   case Drop is
  878.                      when Strings.Right =>
  879.                         Result.Data (1 .. Blen) := Source.Data (1 .. Blen);
  880.  
  881.                         if Droplen > Alen then
  882.                            Result.Data (Low .. Max_Length) :=
  883.                              By (By'First .. By'First + Max_Length - Low);
  884.                         else
  885.                            Result.Data (Low .. Low + By'Length - 1) := By;
  886.                            Result.Data (Low + By'Length .. Max_Length) :=
  887.                              Source.Data (High + 1 .. Slen - Droplen);
  888.                         end if;
  889.  
  890.                      when Strings.Left =>
  891.                         Result.Data (Max_Length - (Alen - 1) .. Max_Length) :=
  892.                           Source.Data (High + 1 .. Slen);
  893.  
  894.                         if Droplen >= Blen then
  895.                            Result.Data (1 .. Max_Length - Alen) :=
  896.                              By (By'Last - (Max_Length - Alen) + 1 .. By'Last);
  897.                         else
  898.                            Result.Data
  899.                              (Blen - Droplen + 1 .. Max_Length - Alen) := By;
  900.                            Result.Data (1 .. Blen - Droplen) :=
  901.                              Source.Data (Droplen + 1 .. Blen);
  902.                         end if;
  903.  
  904.                      when Strings.Error =>
  905.                         raise Strings.Length_Error;
  906.                   end case;
  907.                end if;
  908.  
  909.                return Result;
  910.             end;
  911.          end if;
  912.       end Replace_Slice;
  913.  
  914.       procedure Replace_Slice
  915.          (Source   : in out Bounded_Wide_String;
  916.           Low      : in Positive;
  917.           High     : in Natural;
  918.           By       : in Wide_String;
  919.           Drop     : in Strings.Truncation := Strings.Error) is
  920.  
  921.       begin
  922.          --  We do a double copy here because this is one of the situations
  923.          --  in which we move data to the right, and at least at the moment,
  924.          --  GNAT is not handling such cases correctly ???
  925.  
  926.          Source := Replace_Slice (Source, Low, High, By, Drop);
  927.       end Replace_Slice;
  928.  
  929.       ---------------
  930.       -- Replicate --
  931.       ---------------
  932.  
  933.       function Replicate
  934.         (Count : in Natural;
  935.          Item  : in Wide_Character;
  936.          Drop  : in Strings.Truncation := Strings.Error)
  937.          return  Bounded_Wide_String
  938.       is
  939.          Result : Bounded_Wide_String;
  940.  
  941.       begin
  942.          if Count <= Max_Length then
  943.             Result.Length := Count;
  944.  
  945.          elsif Drop = Strings.Error then
  946.             raise Strings.Length_Error;
  947.  
  948.          else
  949.             Result.Length := Max_Length;
  950.          end if;
  951.  
  952.          Result.Data (1 .. Result.Length) := (others => Item);
  953.          return Result;
  954.       end Replicate;
  955.  
  956.       function Replicate
  957.         (Count : in Natural;
  958.          Item  : in Wide_String;
  959.          Drop  : in Strings.Truncation := Strings.Error)
  960.          return  Bounded_Wide_String
  961.       is
  962.          Length : constant Integer := Count * Item'Length;
  963.          Result : Bounded_Wide_String;
  964.          Indx   : Positive;
  965.  
  966.       begin
  967.          if Length <= Max_Length then
  968.             Result.Length := Length;
  969.             Indx := 1;
  970.  
  971.             for J in 1 .. Count loop
  972.                Result.Data (Indx .. Indx + Item'Length - 1) := Item;
  973.                Indx := Indx + Item'Length;
  974.             end loop;
  975.  
  976.          else
  977.             Result.Length := Max_Length;
  978.  
  979.             case Drop is
  980.                when Strings.Right =>
  981.                   Indx := 1;
  982.  
  983.                   while Indx + Item'Length <= Max_Length + 1 loop
  984.                      Result.Data (Indx .. Indx + Item'Length - 1) := Item;
  985.                      Indx := Indx + Item'Length;
  986.                   end loop;
  987.  
  988.                   Result.Data (Indx .. Max_Length) :=
  989.                     Item (1 .. Max_Length - Indx + 1);
  990.  
  991.                when Strings.Left =>
  992.                   Indx := Max_Length;
  993.  
  994.                   while Indx - Item'Length >= 1 loop
  995.                      Result.Data (Indx - (Item'Length - 1) .. Indx) := Item;
  996.                      Indx := Indx - Item'Length;
  997.                   end loop;
  998.  
  999.                   Result.Data (1 .. Indx) :=
  1000.                     Item (Item'Last - Indx + 1 .. Item'Last);
  1001.  
  1002.                when Strings.Error =>
  1003.                   raise Strings.Length_Error;
  1004.             end case;
  1005.          end if;
  1006.  
  1007.          return Result;
  1008.       end Replicate;
  1009.  
  1010.       function Replicate
  1011.         (Count : in Natural;
  1012.          Item  : in Bounded_Wide_String;
  1013.          Drop  : in Strings.Truncation := Strings.Error)
  1014.          return  Bounded_Wide_String
  1015.       is
  1016.       begin
  1017.  
  1018.          return Replicate (Count, Item.Data (Item.Length), Drop);
  1019.       end Replicate;
  1020.  
  1021.       -----------
  1022.       -- Slice --
  1023.       -----------
  1024.  
  1025.       function Slice
  1026.         (Source : in Bounded_Wide_String;
  1027.          Low    : in Positive;
  1028.          High   : in Natural)
  1029.          return   Wide_String
  1030.       is
  1031.       begin
  1032.          return Source.Data (Low .. High);
  1033.  
  1034.       exception
  1035.          when Constraint_Error =>
  1036.             raise Strings.Index_Error;
  1037.       end Slice;
  1038.  
  1039.       ----------
  1040.       -- Tail --
  1041.       ----------
  1042.  
  1043.       function Tail
  1044.         (Source : in Bounded_Wide_String;
  1045.          Count  : Natural;
  1046.          Pad    : in Wide_Character := Blank;
  1047.          Drop   : in Strings.Truncation := Strings.Error)
  1048.          return   Bounded_Wide_String
  1049.       is
  1050.          Result : Bounded_Wide_String;
  1051.          Slen   : constant Natural := Source.Length;
  1052.          Npad   : constant Integer := Count - Slen;
  1053.  
  1054.       begin
  1055.          if Npad <= 0 then
  1056.             Result.Length := Count;
  1057.             Result.Data (1 .. Count) :=
  1058.               Source.Data (Slen - (Count - 1) .. Slen);
  1059.  
  1060.          elsif Count <= Max_Length then
  1061.             Result.Length := Count;
  1062.             Result.Data (1 .. Npad) := (others => Pad);
  1063.             Result.Data (Npad + 1 .. Count) := Source.Data (1 .. Slen);
  1064.  
  1065.          else
  1066.             Result.Length := Max_Length;
  1067.  
  1068.             case Drop is
  1069.                when Strings.Right =>
  1070.                   if Npad > Max_Length then
  1071.                      Result.Data := (others => Pad);
  1072.  
  1073.                   else
  1074.                      Result.Data (1 .. Npad) := (others => Pad);
  1075.                      Result.Data (Npad + 1 .. Max_Length) :=
  1076.                        Source.Data (1 .. Max_Length - Npad);
  1077.                   end if;
  1078.  
  1079.                when Strings.Left =>
  1080.                   Result.Data (1 .. Max_Length - Slen) := (others => Pad);
  1081.                   Result.Data (Max_Length - Slen + 1 .. Max_Length) :=
  1082.                     Source.Data (1 .. Slen);
  1083.  
  1084.                when Strings.Error =>
  1085.                   raise Strings.Length_Error;
  1086.             end case;
  1087.          end if;
  1088.  
  1089.          return Result;
  1090.       end Tail;
  1091.  
  1092.       ----------------------------
  1093.       -- To_Bounded_Wide_String --
  1094.       ----------------------------
  1095.  
  1096.       function To_Bounded_Wide_String
  1097.         (Source : in Wide_String;
  1098.          Drop   : in Strings.Truncation := Strings.Error)
  1099.          return   Bounded_Wide_String
  1100.       is
  1101.          Slen   : constant Positive := Source'Length;
  1102.          Result : Bounded_Wide_String;
  1103.  
  1104.       begin
  1105.          if Slen <= Max_Length then
  1106.             Result.Length := Slen;
  1107.             Result.Data (1 .. Slen) := Source;
  1108.  
  1109.          else
  1110.             case Drop is
  1111.                when Strings.Right =>
  1112.                   Result.Length := Max_Length;
  1113.                   Result.Data (1 .. Max_Length) := Source (1 .. Max_Length);
  1114.  
  1115.                when Strings.Left =>
  1116.                   Result.Length := Max_Length;
  1117.                   Result.Data (1 .. Max_Length) :=
  1118.                     Source (Slen - (Max_Length - 1) .. Slen);
  1119.  
  1120.                when Strings.Error =>
  1121.                   raise Strings.Length_Error;
  1122.             end case;
  1123.          end if;
  1124.  
  1125.          return Result;
  1126.       end To_Bounded_Wide_String;
  1127.  
  1128.       --------------------
  1129.       -- To_Wide_String --
  1130.       --------------------
  1131.  
  1132.       function To_Wide_String
  1133.         (Source : in Bounded_Wide_String)
  1134.          return   Wide_String
  1135.       is
  1136.       begin
  1137.          return Source.Data (1 .. Source.Length);
  1138.       end To_Wide_String;
  1139.  
  1140.       ---------------
  1141.       -- Translate --
  1142.       ---------------
  1143.  
  1144.       function Translate
  1145.         (Source  : in Bounded_Wide_String;
  1146.          Mapping : in Wide_Maps.Wide_Character_Mapping)
  1147.          return    Bounded_Wide_String
  1148.       is
  1149.          Result : Bounded_Wide_String;
  1150.  
  1151.       begin
  1152.          Result.Length := Source.Length;
  1153.  
  1154.          for J in 1 .. Source.Length loop
  1155.             Result.Data (J) := Value (Mapping, Source.Data (J));
  1156.          end loop;
  1157.  
  1158.          return Result;
  1159.       end Translate;
  1160.  
  1161.       procedure Translate
  1162.         (Source  : in out Bounded_Wide_String;
  1163.          Mapping : in Wide_Maps.Wide_Character_Mapping)
  1164.       is
  1165.       begin
  1166.          for J in 1 .. Source.Length loop
  1167.             Source.Data (J) := Value (Mapping, Source.Data (J));
  1168.          end loop;
  1169.       end Translate;
  1170.  
  1171.       function Translate
  1172.         (Source  : in Bounded_Wide_String;
  1173.          Mapping : in Wide_Maps.Wide_Character_Mapping_Function)
  1174.          return    Bounded_Wide_String
  1175.       is
  1176.          Result : Bounded_Wide_String;
  1177.  
  1178.       begin
  1179.          Result.Length := Source.Length;
  1180.  
  1181.          for J in 1 .. Source.Length loop
  1182.             Result.Data (J) := Mapping (Source.Data (J));
  1183.          end loop;
  1184.  
  1185.          return Result;
  1186.       end Translate;
  1187.  
  1188.       procedure Translate
  1189.         (Source : in out Bounded_Wide_String;
  1190.          Mapping  : in Wide_Maps.Wide_Character_Mapping_Function) is
  1191.  
  1192.       begin
  1193.          for J in 1 .. Source.Length loop
  1194.             Source.Data (J) := Mapping (Source.Data (J));
  1195.          end loop;
  1196.       end Translate;
  1197.  
  1198.       ----------
  1199.       -- Trim --
  1200.       ----------
  1201.  
  1202.       function Trim
  1203.         (Source : in Bounded_Wide_String)
  1204.          return   Bounded_Wide_String
  1205.       is
  1206.          Result : Bounded_Wide_String;
  1207.          J      : Positive;
  1208.  
  1209.       begin
  1210.          for I in 1 .. Source.Length loop
  1211.             if Source.Data (I) /= ' ' then
  1212.                J := Source.Length;
  1213.  
  1214.                while Source.Data (J) = ' ' loop
  1215.                   J := J - 1;
  1216.                end loop;
  1217.  
  1218.                Result.Length := J - I + 1;
  1219.                Result.Data (1 .. Result.Length) := Source.Data (I .. J);
  1220.             end if;
  1221.          end loop;
  1222.  
  1223.          Result.Length := 0;
  1224.          return Result;
  1225.       end Trim;
  1226.  
  1227.       function Trim
  1228.         (Source : in Bounded_Wide_String;
  1229.          Left   : in Wide_Maps.Wide_Character_Set;
  1230.          Right  : in Wide_Maps.Wide_Character_Set)
  1231.          return   Bounded_Wide_String
  1232.       is
  1233.          Result : Bounded_Wide_String;
  1234.  
  1235.       begin
  1236.          for J in 1 .. Source.Length loop
  1237.             if not Is_In (Source.Data (J), Left) then
  1238.                for K in reverse J .. Source.Length loop
  1239.                   if not Is_In (Source.Data (K), Right) then
  1240.                      Result.Length := K - J + 1;
  1241.                      Result.Data (1 .. Result.Length) := Source.Data (J .. K);
  1242.                      return Result;
  1243.                   end if;
  1244.                end loop;
  1245.             else
  1246.                exit;
  1247.             end if;
  1248.          end loop;
  1249.  
  1250.          Result.Length := 0;
  1251.          return Result;
  1252.       end Trim;
  1253.  
  1254.       procedure Trim
  1255.         (Source : in out Bounded_Wide_String;
  1256.          Left   : in Wide_Maps.Wide_Character_Set;
  1257.          Right  : in Wide_Maps.Wide_Character_Set)
  1258.       is
  1259.       begin
  1260.          for J in 1 .. Source.Length loop
  1261.             if not Is_In (Source.Data (J), Left) then
  1262.                for K in reverse J .. Source.Length loop
  1263.                   if not Is_In (Source.Data (K), Right) then
  1264.                      if J = 1 then
  1265.                         Source.Length := K;
  1266.                         return;
  1267.                      else
  1268.                         Source.Length := K - J + 1;
  1269.                         Source.Data (1 .. Source.Length) :=
  1270.                           Source.Data (J .. K);
  1271.                      end if;
  1272.                   end if;
  1273.                end loop;
  1274.             else
  1275.                exit;
  1276.             end if;
  1277.          end loop;
  1278.  
  1279.          Source.Length := 0;
  1280.       end Trim;
  1281.  
  1282.    end Generic_Bounded_Length;
  1283.  
  1284. end Ada.Strings.Wide_Bounded;
  1285.